
#ifndef __ARCHIVOBITMAP_H__
#define __ARCHIVOBITMAP_H__

 //Inclusiones necesarias
#include <fstream>
#include <iostream>
//Definicion de la estructura del archivo Bitmap
 typedef struct {
 char bm[2];
 int tamano;
 int reservado;
int offset;
 int tamanoMetadatos;
 int altoEnPixels;
 int anchoEnPixels;
 short numeroPlanos;
 short profundidadColor;
 int tipoCompresion;
 int tamanoEstructura;
 int pxmh;
 int pxmv;
 int coloresUsados;
 int coloresImportantes;
 } tipoMetadatosBMP;
 
 
class ArchivoBitmap{

 /**
 * Colores que vamos a utilizar en el TP. Solo utilizaremos blanco y negro
identificados
por
44: * caracteres, aunque el archivo tenga una profundidad de color de 24bits. Es
decir cada
color
45: * del archivo esta representado por 3 enteros de un byte cada uno. Nosotros
vamos a tomar
el
46: * color negro y todos los demas se van a tomar como blanco.
47: */

public:
       static const int BLANCO =-1;
       static const int NEGRO = 1;
       static const int PROFUNDIDADDE24BITS = 24;

 private:
 //Matriz para levantar los colores en memoria. Solo vamos a trabajar con 2
 int ** colores;
 //cuenta los pixeles que el bitmap tiene de ancho, lo cual da la dimension x
 int anchoArreglo;
 //cuenta los pixeles que el bitmap tiene de alto, lo cual da la dimension y

 int altoArreglo;
 public:
/**
 * Abre el archivo ubicado en el path pasado (debe incluir nombre completo o
relativo al
exe) en modo lectura.
64: * Deja el cursor al comienzo del mismo.
65: * En caso de no existir el archivo, lo crea.
66: * Si no puede realizar la operación, arroja una excepción
67: */
 ArchivoBitmap(const std::string& path){

 this->colores = NULL;

 // referencia al archivo
 std::fstream archivo;

 //intenta abrir el archivo en modo lectura y binario
 archivo.open(path.c_str(), std::fstream::in | std::fstream::binary
);

//verifico la apertura del mismo, sino devuelve error.
if (!archivo.is_open()) {
archivo.close();
throw std::ios_base::failure("El archivo no pudo ser abierto");
 }


//la primera parte del archivo son los datos del bitmap, los cargo en la
 tipoMetadatosBMP imagen;
 archivo.read((char *)&imagen.bm,2);
 archivo.read((char *)&imagen.tamano,sizeof(imagen.tamano));
 archivo.read((char *)&imagen.reservado,sizeof(imagen.reservado));
 archivo.read((char *)&imagen.offset,sizeof(imagen.offset));
 archivo.read((char*)&imagen.tamanoMetadatos,sizeof(imagen.tamanoMetadatos));
 archivo.read((char*)&imagen.anchoEnPixels,sizeof(imagen.anchoEnPixels));
 this->altoArreglo = imagen.anchoEnPixels;
 archivo.read((char*)&imagen.altoEnPixels,sizeof(imagen.altoEnPixels));
 this->anchoArreglo = imagen.altoEnPixels;
 archivo.read((char*)&imagen.numeroPlanos,sizeof(imagen.numeroPlanos));
 archivo.read((char*)&imagen.profundidadColor,sizeof(imagen.profundidadColor));

 archivo.read((char*)&imagen.tipoCompresion,sizeof(imagen.tipoCompresion));
 archivo.read((char*)&imagen.tamanoEstructura,sizeof(imagen.tamanoEstructura));
 archivo.read((char *)&imagen.pxmh,sizeof(imagen.pxmh));
 archivo.read((char *)&imagen.pxmv,sizeof(imagen.pxmv));
 archivo.read((char*)&imagen.coloresUsados,sizeof(imagen.coloresUsados));
 archivo.read((char*)&imagen.coloresImportantes,sizeof(imagen.coloresImportantes));

 //verifico que la profundidad del bitmap sea de 24 bits
 if (imagen.profundidadColor != ArchivoBitmap::PROFUNDIDADDE24BITS ){
 throw std::ios_base::failure("El archivo no es de 24bits");
 }

 //creo la matriz con las dimensiones del bitmap, un pixel para cada
 this->colores = new int*[imagen.altoEnPixels];
 for (int i = 0;i < imagen.altoEnPixels; i++){
this->colores[i] = new int [imagen.anchoEnPixels];
 }

 //el bitmap tiene pixeles de relleno, los calculo para leerlos y no

 int resto = imagen.anchoEnPixels % 4;

 //cargo la matriz con los datos del archivo
 for (int i=1 ; i <= imagen.altoEnPixels ; i++){
 for (int j=1;j <= imagen.anchoEnPixels;j++ ) {
 char temp[3] = "";
 archivo.read((char *)&temp,3);
 this->colores[i-1][j-1] = ArchivoBitmap::BLANCO;
 if ( temp[0] == '\0' ) this->colores[i-1][j-1] =
ArchivoBitmap::NEGRO;
 }

//leo los pixeles de relleno y los paso por alto.
 for (int k=1;k<=resto;k++){
 int temp = 0;
 archivo.read((char *)&temp,1);
 }
 }

 //cierro el archivo para su liberacion
 archivo.close();
 }

 /**
 * libero la memoria que ocupa la matriz
*/
 ~ArchivoBitmap(){
 if ( this->colores != NULL) {
 for (int i = 0;i < this->getAncho(); i++){
 delete[] this->colores[i];
 }
 delete[] this->colores;
 }
 }



 int obtenerColor(int x, int y){
 if ( x < 0 ) throw std::ios_base::failure("El parametro x debe ser positivo");
 if ( y < 0 ) throw std::ios_base::failure("El parametro y debe ser mpositivo");
 if ( x >= this->anchoArreglo) throw std::ios_base::failure("El que el ancho del bitmap");
 if ( y >= this->altoArreglo) throw std::ios_base::failure("El parametro y es mayor que el alto del bitmap");

 if ( this->colores != NULL) return this->colores[this->anchoArreglo- x - 1][y];
 throw std::ios_base::failure("Error al leer el Archivo");
 }

 /**
 * Devuelve el alto del bitmap.
 */
 int getAlto(){
 return this->altoArreglo;
 }

 /**
 * Devuelve el ancho del bitmap.
 */
 int getAncho(){
 return this->anchoArreglo;
 }

 };
 
 #endif

